package com.zhongan.filter.post;

import com.alibaba.fastjson.JSON;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.zhongan.dto.ApiFinalResponse;
import com.zhongan.dto.ApiRequest;
import com.zhongan.dto.ApiResponse;
import com.zhongan.enums.ApiMsgEnum;
import com.zhongan.enums.ZsfFilterType;
import com.zhongan.util.WebHelper;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.stereotype.Component;
import org.springframework.web.util.WebUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 日志拦截器
 * 系统日志追踪
 *
 * @author za-shaojian
 * @create 2017-10-26 15:58
 **/
@Component
public class LoggerFilter extends ZuulFilter {

    private static final Logger logger = Logger.getLogger(LoggerFilter.class);
    private static final Map<Long, String> logMap = new HashMap<Long, String>();
    private static int localPort = 0;
    public static final String LOG_ID = "logId";

    @Autowired
    Tracer tracer;

    @Override
    public String filterType() {
        return ZsfFilterType.POST_TYPE.getCode();
    }

    @Override
    public int filterOrder() {
        return 900;
    }

    /**
     * 过滤器进行过滤路径设置
     * @return
     */
    public boolean shouldFilter() {
        String requestUri = RequestContext.getCurrentContext().getRequest().getRequestURI();
        //过滤掉swagger相关的请求
        if(requestUri.contains("swagger-ui") || requestUri.contains("swagger-resources") || requestUri.contains("v2/api-docs")){
            return false;
        }
        return true;
    }

    public Object run() {
        try {
            long start = System.currentTimeMillis();
            long stop = 0;
            RequestContext ctx = RequestContext.getCurrentContext();
            HttpServletRequest request = ctx.getRequest();
            //封装请求信息日志
            String logId = tracer.getCurrentSpan().traceIdString();
            long threadId = Thread.currentThread().getId();
            if (localPort == 0) {
                localPort = request.getLocalPort();
            }
            String referer = request.getHeader("referer");
            logMap.put(threadId, logId);
            request.setAttribute(LOG_ID, logId);
            String attribute = getAttributeLog(request);
            StringBuffer buf = new StringBuffer("{");
            long end = System.currentTimeMillis() - start;
            ApiRequest apiRequest = new ApiRequest();
            Map<String, String> requestMap = new HashMap<String, String>();
            requestMap.put("tracerId", tracer.getCurrentSpan().traceIdString());
            requestMap.put("totalTime", String.valueOf(end));
            requestMap.put("requestParam", attribute);
            logMap.remove(threadId);
            tracer.addTag("referer", referer);
            tracer.addTag("requestIP", WebHelper.getRequestIp(request));
            tracer.addTag("requestURI", getRequestUri(request));
            tracer.addTag("method", request.getMethod());
            tracer.addTag("requestAttribute", attribute);
            logger.info("客户端调用请求开始[接口:[" + getRequestUri(request) + "，开始时间:" + start + "，请求参数：" + JSON.toJSONString(requestMap) + "]");
            String results = ctx.getResponseBody();
            StringBuffer out = new StringBuffer();
            if (results == null) {
                InputStream inputStream = ctx.getResponseDataStream();
                if(inputStream!=null){
                    byte[] b = new byte[4096];
                    try {
                        for (int n; (n = inputStream.read(b)) != -1; ) {
                            out.append(new String(b, 0, n));
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    results = out.toString();
                }
            }
            ApiFinalResponse finalRsp = new ApiFinalResponse();
            finalRsp.setResults(results);
            tracer.addTag("responseResult", JSON.toJSONString(finalRsp));
            logger.info("客户端调用请求结束[接口:[" + getRequestUri(request) + "，方法:" + request.getMethod() + "，调用结果："
                    + JSON.toJSONString(finalRsp) + "结束时间:" + stop + ",耗时:" + (stop - start) + "ms" + "]");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(ApiMsgEnum.FAIL);
        }
        return null;
    }

    private static String getAttributeLog(HttpServletRequest request) {
        Map<String, String> attribute = new HashMap<String, String>();
        Enumeration<String> attrNames = request.getParameterNames();
        while (attrNames.hasMoreElements()) {
            String attrName = attrNames.nextElement();
            attribute.put(attrName, request.getParameter(attrName));
        }
        return JSON.toJSONString(attribute);
    }

    private static String getRequestUri(HttpServletRequest request) {
        String uri = (String) request.getAttribute(WebUtils.INCLUDE_REQUEST_URI_ATTRIBUTE);
        if (uri == null) {
            uri = request.getRequestURI();
        }
        return uri;
    }
}
